// https://leetcode.cn/problems/buddy-strings/
// Created by ade on 2022/8/17.
// 给你两个字符串 s 和 goal ，只要我们可以通过交换 s 中的两个字母得到与 goal 相等的结果，就返回 true ；否则返回 false 。
//
// 交换字母的定义是：取两个下标 i 和 j （下标从 0 开始）且满足 i != j ，接着交换 s[i] 和 s[j] 处的字符。【只能交换一次】
//
// 例如，在 "abcd" 中交换下标 0 和下标 2 的元素可以生成 "cbad" 。
#include <iostream>
#include <algorithm>
#include <string>


using namespace std;

class Solution {
public:
    bool buddyStrings1(string s, string goal) {
        int len1 = s.size();
        int len2 = goal.size();
        if (len1 != len2) return false;

        if (s == goal) {
            unordered_map<char, int> m = {};
            for (auto i : s) {
                m[i]++;
                if (m[i] > 1) return true;
            }
            return false;
        } else {
            string ss = s;
            string sg = goal;
            sort(ss.begin(), ss.end());
            sort(sg.begin(), sg.end());
            if (ss != sg) return false;
            int num = 0;
            for (int i = 0; i < len1; i++) {
                if (s[i] != goal[i]) {
                    num++;
                }
            }
            return num == 2;
        }
    }

    // 第二种方式更优
    bool buddyStrings(string s, string goal) {
        int len1 = s.size();
        int len2 = goal.size();
        if (len1 != len2) return false;
        int m1[26] = {0};
        int m2[26] = {0};

        int num = 0;
        for (int i = 0; i < len1; i++) {
            m1[s[i] - 'a']++;
            m2[goal[i] - 'a']++;
            if (s[i] != goal[i]) {
                num++;
            }
        }
        int hasDouble = 0
        for (int i = 0; i < 26; i++) {
            if (m1[i] != m2[i]) return false;
            if (m1[i] > 1) hasDouble = 1;

        }
        return num == 2 || num == 0 && hasDouble;
    }
};